﻿using System;
using System.Net;
using System.Security.Cryptography.X509Certificates;
using System.ServiceModel;

namespace WOLGateway.PresentationService
{
    /// <summary>
    /// Proxy
    /// </summary>
    public class Proxy
    {
        /// <summary>
        /// Async WCF call completed with results
        /// </summary>
        public event EventHandler<StringEventArgs> OnSendMagicPacketToCompleted;

        /// <summary>
        /// Async WCF call failed
        /// </summary>
        public event EventHandler<StringEventArgs> OnSendMagicPacketToFailed;

        /// <summary>
        /// WakeOnLan Service reference client
        /// </summary>
        private WOLGatewayServiceReference.WakeOnLanClient wolClient;

        /// <summary>
        /// Constructor
        /// </summary>
        /// <param name="wolGatewayServerUrl">The WOLGateway Service URL</param>
        /// <param name="ignoreServerCertificateValidation">Ignore Server Certificate Validation (i.e. for self signed SSL certs)</param>
        public Proxy(string wolGatewayServerUrl, bool ignoreServerCertificateValidation)
        {
            if (ignoreServerCertificateValidation)
            {
                ServicePointManager.ServerCertificateValidationCallback += new System.Net.Security.RemoteCertificateValidationCallback(IgnoreServerCertificateValidation);
            }

            var remoteAddress = new EndpointAddress(wolGatewayServerUrl);
            var binding = new BasicHttpBinding();
            binding.ReceiveTimeout = TimeSpan.FromMinutes(1);
            binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.None;

            if (wolGatewayServerUrl.StartsWith("http://"))
            {
                binding.Security.Mode = BasicHttpSecurityMode.None;
            }
            else if (wolGatewayServerUrl.StartsWith("https://"))
            {
                binding.Security.Mode = BasicHttpSecurityMode.Transport;
            }
            else
            {
                throw new ApplicationException("WOLGateway Server URL must start with http:// or with https://");
            }

            wolClient = new WOLGatewayServiceReference.WakeOnLanClient(binding, remoteAddress);
        }

        /// <summary>
        /// Send magic packet to given MacAddress
        /// </summary>
        /// <param name="macAddress">The MAC address of the computer to be woken up</param>
        public void BeginSendMagicPacketTo(string macAddress)
        {
            if (string.IsNullOrEmpty(macAddress)
                || macAddress == "00-00-00-00-00-00")
            {
                throw new ApplicationException("The MAC-Address of the computer to be woken up has not yet been specified. Please enter it save the options first.");
            }

            wolClient.BeginSendMagicPacketTo(macAddress, EndSendMagicPacketTo, null);
        }

        /// <summary>
        /// Async callback for SendMagicPacketTo
        /// </summary>
        /// <param name="result">Async Result</param>
        private void EndSendMagicPacketTo(IAsyncResult result)
        {
            try
            {
                string message = wolClient.EndSendMagicPacketTo(result);
                var eventArg = new StringEventArgs(message);
                if (OnSendMagicPacketToCompleted != null)
                {
                    OnSendMagicPacketToCompleted(this, eventArg);
                }
            }
            catch (Exception ex)
            {
                if (OnSendMagicPacketToFailed != null)
                {
                    var eventArg = new StringEventArgs(ex.Message);
                    OnSendMagicPacketToFailed(this, eventArg);
                }
            }
        }

        /// <summary>
        /// Easy certificate check
        /// </summary>
        /// <param name="sender">The parameter is not used.</param>
        /// <param name="cert">The parameter is not used.</param>
        /// <param name="chain">The parameter is not used.</param>
        /// <param name="error">The parameter is not used.</param>
        /// <returns>Always returns true</returns>
        private bool IgnoreServerCertificateValidation(object sender, X509Certificate cert, X509Chain chain, System.Net.Security.SslPolicyErrors error)
        {
            return true;
        }
    }
}
